package cn.qingyun.gis.modules.takeaway.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.qingyun.gis.exception.CommonException;
import cn.qingyun.gis.modules.express.constant.ExpressStatus;
import cn.qingyun.gis.modules.express.constant.RedisContant;
import cn.qingyun.gis.modules.express.entity.OperationLog;
import cn.qingyun.gis.modules.express.mapper.OperationLogMapper;
import cn.qingyun.gis.modules.express.request.ExpressProofreadRequest;
import cn.qingyun.gis.modules.express.request.ExpressQueryRequest;
import cn.qingyun.gis.modules.init.system.constant.enums.RegionNumPermissionEnum;
import cn.qingyun.gis.modules.takeaway.entity.TakeawayInfo;
import cn.qingyun.gis.modules.takeaway.entity.TakeawayProofread;
import cn.qingyun.gis.modules.takeaway.entity.dto.TakeawayTotalDto;
import cn.qingyun.gis.modules.takeaway.mapper.TakeawayInfoMapper;
import cn.qingyun.gis.modules.takeaway.mapper.TakeawayProofreadMapper;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayAttachmentService;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayProofreadService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 外卖勘误 服务实现类
 * </p>
 *
 * @author guest
 * @since 2023-10-26
 */
@Service
public class TakeawayProofreadServiceImpl extends ServiceImpl<TakeawayProofreadMapper, TakeawayProofread> implements ITakeawayProofreadService {
    @Resource
    private TakeawayProofreadMapper takeawayProofreadMapper;
    @Resource
    private TakeawayInfoMapper takeawayInfoMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private ITakeawayAttachmentService iTakeawayAttachmentService;
    @Resource
    private OperationLogMapper operationLogMapper;

    @Override
    public IPage<TakeawayProofread> queryList(ExpressQueryRequest request) {
        //根据网格编码+工号+未勘误（勘误状态=0）+校对类型+修改时间降序匹配查询
        QueryWrapper<TakeawayProofread> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(request.getLat()) || ObjectUtil.isNotEmpty(request.getLon())){
            queryWrapper.select("takeaway_proofread.*," + String.format("ROUND(ST_Distance_Sphere(POINT(%s, %s), POINT(lon, lat))/1000,2) AS distance", request.getLon(), request.getLat()))
                    .orderByAsc("distance is null,distance");
        }
        queryWrapper.lambda().eq(TakeawayProofread::getKwStatus, ExpressStatus.UN_PROOFED).orderByDesc(TakeawayProofread::getUpdateTime);
        String[] gridIdStr = request.getGridId().split(",");
        List<String> gridIdList = Arrays.asList(gridIdStr);

        //创建分页对象
        IPage<TakeawayProofread> page = new Page<>(request.getPageNum(), request.getPageSize());

        // 根据区域权限进行判定 以及 关键字模糊查询
        if (CharSequenceUtil.isNotEmpty(request.getGridType()) && Boolean.TRUE.equals(RegionNumPermissionEnum.pitchRegion(request.getGridType()))) {
            if (ObjectUtil.isNotEmpty(request.getKeyword())) {
                queryWrapper.lambda().and(
                        lwp -> lwp.like(TakeawayProofread::getPoiAddress, request.getKeyword()).
                                or().
                                like(TakeawayProofread::getPoiName, request.getKeyword())
                );
            }
            if (RegionNumPermissionEnum.PROVINCE.name().equals(request.getGridType()) && gridIdList.size() == 1) {
                return takeawayProofreadMapper.selectPage(page, queryWrapper);
            } else {
                queryWrapper.lambda().and(
                        wp -> wp.in(TakeawayProofread::getRegionCityCode, gridIdList).
                                or().
                                in(TakeawayProofread::getRegionDistrictsCode, gridIdList).
                                or().
                                in(TakeawayProofread::getGridId, gridIdList)
                );
            }
            return takeawayProofreadMapper.selectPage(page, queryWrapper);
        }
        return new Page<>();
    }

    @Override
    @Transactional
    public String takeawayProofread(ExpressProofreadRequest request) {
        RLock rlock = redissonClient.getLock(RedisContant.TAKEAWAY_PROOF_LOCK);
        try {
            boolean lockRes = rlock.tryLock(10, TimeUnit.SECONDS);
            if (lockRes) {
                //1.处理express_proofread表
                TakeawayProofread proofread = takeawayProofreadMapper.selectById(request.getId());
                BeanUtil.copyProperties(request, proofread);
                proofread.setKwStatus(ExpressStatus.PROOFED); //更新勘误状态
                proofread.setUpdateTime(DateUtil.date());//更新修改(勘误)时间
                if(request.getGridBelongStatus() == 0){ // 优化：若勘误过程，站点不属于本网格，选择应属网格，勘误状态更新为：未勘误
                    proofread.setKwStatus(ExpressStatus.UN_PROOFED);
                    // 自动进行应归属网格匹配
                    proofread.setGridName(request.getBelongGrid());
                    proofread.setGridId(request.getBelongGridCode());
                    proofread.setRegionDistricts(request.getBelongCounty());
                    proofread.setRegionDistrictsCode(request.getBelongCountyCode());
                    // 添加日志
                    OperationLog operationLog = OperationLog.builder()
                            .logAccount(request.getKwPhone())
                            .operationId(request.getId())
                            .logType(0) // 0:应属网格操作
                            .operateType(1)  //1:外卖
                            .createTime(DateUtil.date()).build();
                    operationLogMapper.insert(operationLog);
                }
                takeawayProofreadMapper.updateById(proofread);

                //2.处理takeaway_info表
                TakeawayInfo res = takeawayInfoMapper.selectOne(new LambdaQueryWrapper<TakeawayInfo>().eq(TakeawayInfo::getTakeawayProofreadId, request.getId()));
                TakeawayInfo info = new TakeawayInfo();
                if (ObjectUtil.isEmpty(res)) { //该外卖地址还未勘误
                    BeanUtil.copyProperties(request, info); //接收第一次勘误数据
                    info.setId(null); // 更新id
                    info.setTakeawayProofreadId(request.getId());
                    info.setCreateTime(DateUtil.date()); // 初次勘误时间记录
                    info.setUpdateTime(DateUtil.date()); // 初次修改时间
                    takeawayInfoMapper.insert(info);
                } else {//外卖地址已勘误一次
                    BeanUtil.copyProperties(request, info);//接收第二次勘误数据
                    info.setId(res.getId()); // 记录第一次勘误保存的id
                    info.setTakeawayProofreadId(request.getId()); // 主表id
                    info.setUpdateTime(DateUtil.date()); //勘误修改时间记录
                    takeawayInfoMapper.updateById(info);
                }
                //3.图片上传
                iTakeawayAttachmentService.upload(request.getPictureList(), request.getId());
                return "勘误成功";
            }
            return "系统繁忙，请稍后再试";

        } catch (Exception e) {
            throw new CommonException("勘误失败",e);
        } finally {
            rlock.unlock();
        }
    }

    @Override
    public IPage<TakeawayTotalDto> queryTotalList(ExpressQueryRequest request) {
        //创建分页对象
        IPage<TakeawayTotalDto> page = new Page<>(request.getPageNum(), request.getPageSize());

        List<String> gridEncodings = Arrays.asList(request.getGridId().split(","));
        String gridType = request.getGridType();

        // 根据区域权限进行判定
        if (CharSequenceUtil.isNotEmpty(gridType) && RegionNumPermissionEnum.pitchRegion(request.getGridType())) {
            return page.setRecords(takeawayProofreadMapper.selectTakeawayTotalList(page, gridEncodings, gridType,request.getKeyword(),request.getLon(),request.getLat()));
        }
        return new Page<>();
    }

    @Override
    public TakeawayTotalDto queryProofreadById(String id) {
        return takeawayProofreadMapper.queryProofreadById(id);
    }
}
